﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ArgusMedia.Video
{
	public struct KrKbConstants
	{
		public double Kr { get; private set; }
		public double Kb { get; private set; }

		public KrKbConstants(double Kr, double Kb)
			: this()
		{
			this.Kr = Kr;
			this.Kb = Kb;
		}

		/// <summary>Standard for SDTV</summary>
		public static KrKbConstants ITU_R_BT_601 { get { return new KrKbConstants(0.299, 0.114); } }
		/// <summary>Standard for HDTV</summary>
		public static KrKbConstants ITU_R_BT_709 { get { return new KrKbConstants(0.2126, 0.0722); } }
	}

	/// <summary>
	/// http://de.wikipedia.org/wiki/YCbCr-Farbmodell#Umrechnung_zwischen_RGB_und_YCbCr
	/// </summary>
	public static class ColorspaceConverter
	{
		public static double[] NormalizeRgb(Color c)
		{
			double[] data = new double[3];
			data[0] = c.R / 255.0;
			data[1] = c.G / 255.0;
			data[2] = c.B / 255.0;
			return data;
		}

		public static double[] Rgb_To_YPbPr(Color c, KrKbConstants KrKb)
		{
			double[] nRgb = ColorspaceConverter.NormalizeRgb(c);
			return ColorspaceConverter.Rgb_To_YPbPr(nRgb, KrKb);
		}

		/// <summary>
		/// Convert normalized RGB to Y'PbPr
		/// </summary>
		public static double[] Rgb_To_YPbPr(double[] Rgb, KrKbConstants KrKb)
		{
			double[] data = new double[3];
			data[0] = KrKb.Kr * Rgb[0] + (1 - KrKb.Kr - KrKb.Kb) * Rgb[1] + KrKb.Kb * Rgb[2];
			data[1] = 0.5 * (Rgb[2] - data[0]) / (1 - KrKb.Kb);
			data[2] = 0.5 * (Rgb[0] - data[0]) / (1 - KrKb.Kr);
			return data;
		}

		public static byte[] YPbPr_To_YCbCr(double[] YPbPr, byte Reserve)
		{
			byte[] data = new byte[3];
			int range = 255-2*Reserve;
			data[0] = (byte)(Reserve + range * YPbPr[0]);
			data[1] = (byte)(128 + range * YPbPr[1]);
			data[2] = (byte)(128 + range * YPbPr[2]);
			return data;
		}

		public static byte[] Rgb_To_YCbCr(Color c, KrKbConstants KrKb, byte Reserve)
		{
			double[] YPbPr = ColorspaceConverter.Rgb_To_YPbPr(c, KrKb);
			return ColorspaceConverter.YPbPr_To_YCbCr(YPbPr, Reserve);
		}
	}
}
